﻿// //------------------------------------------------------------------------------
// // <copyright file="" company="Dascoba Development">
// //  Copyright © Dascoba Development 2010
// // </copyright>
// //------------------------------------------------------------------------------
using System;
using System.Collections.Generic;
using System.Linq;

namespace Dascoba.Umb.FileManager.Support
{
    using System.Drawing;
    using System.Drawing.Drawing2D;
    using System.Drawing.Imaging;
    using System.IO;
    using System.Xml;

    using Dascoba.Umb.FileManager.Config;

    using umbraco;
    using umbraco.cms.businesslogic.media;

    public static class Media
    {
        /// <summary>
        ///   Creates multiple media.
        /// </summary>
        /// <param name = "folderUrl">The folder URL.</param>
        /// <param name = "parentId">The parent id.</param>
        /// <param name = "mediaTypeAlias">The media type alias.</param>
        /// <param name = "moveFiles">if set to <c>true</c> [move files].</param>
        /// <returns></returns>
        internal static List<umbraco.cms.businesslogic.media.Media> ImportFolderMedia(
            string folderUrl, int parentId, string mediaTypeAlias, bool moveFiles)
        {
            var medias = new List<umbraco.cms.businesslogic.media.Media>();

            if (folderUrl == string.Empty)
            {
                medias.Add(null);
                return medias;
            }

            var folderInfo = new DirectoryInfo(Util.MapPath(folderUrl));

            // loop through sub files (no sub folders) and create media for each
            foreach (var fileInfo in folderInfo.GetFiles())
            {
                var fileUrl = Util.MapUrl(fileInfo.FullName);
                var canCreate = FileManagerConfig.IsFileVisible(fileUrl);

                if (!canCreate)
                {
                    continue;
                }
                var singleMedia = ImportFileMedia(fileUrl, parentId, mediaTypeAlias, moveFiles);
                if (singleMedia != null)
                {
                    medias.Add(singleMedia);
                }
            }

            return medias;
        }

        /// <summary>
        ///   Creates a single media.
        /// </summary>
        /// <param name = "fileUrl">The item URL.</param>
        /// <param name = "parentId">The parent id.</param>
        /// <param name = "mediaTypeAlias">The media type alias.</param>
        /// <param name = "moveFile">if set to <c>true</c> [move file].</param>
        /// <returns></returns>
        internal static umbraco.cms.businesslogic.media.Media ImportFileMedia(
            string fileUrl, int parentId, string mediaTypeAlias, bool moveFile)
        {
            if (fileUrl == string.Empty)
            {
                return null;
            }

            var isFolder = mediaTypeAlias == "Folder";

            var mediaFolderPath = Util.MapPath(string.Format("{0}/../media", GlobalSettings.Path));
            var mediaFolderUrl = Util.MapUrl(mediaFolderPath);

            var itemPath = Util.MapUrl(fileUrl);

            var mediaName = isFolder
                                ? new DirectoryInfo(itemPath).Name.ToLower()
                                : new FileInfo(itemPath).Name.ToLower();

            umbraco.cms.businesslogic.media.Media mediaItem = null;
            try
            {
                // create the Media Node
                mediaItem = umbraco.cms.businesslogic.media.Media.MakeNew(
                    mediaName, MediaType.GetByAlias(mediaTypeAlias), umbraco.BusinessLogic.User.GetUser(0), parentId);
            }
            catch
            {
                if (mediaItem != null)
                {
                    mediaItem.delete();
                }

                return null;
            }

            if (isFolder)
            {
                return mediaItem;
            }

            // Create a new folder at /media/id
            var mediaItemFolderUrl = string.Format("{0}/{1}", mediaFolderUrl, mediaItem.Id);
            var mediaItemFileUrl = string.Format("{0}/{1}", mediaItemFolderUrl, mediaName);
            Directory.CreateDirectory(Util.MapPath(mediaItemFolderUrl));

            var fileInfo = new FileInfo(Util.MapPath(fileUrl));

            if (moveFile)
            {
                fileInfo.MoveTo(Util.MapPath(mediaItemFileUrl));
            }
            else
            {
                fileInfo.CopyTo(Util.MapPath(mediaItemFileUrl), false);
            }

            var ext = Util.GetSimpleExtension(fileUrl);

            // Save extension
            try
            {
                mediaItem.getProperty("umbracoExtension").Value = ext.ToLower();
            }
            catch
            {
            }

            // Save file size
            try
            {
                mediaItem.getProperty("umbracoBytes").Value = fileInfo.Length.ToString();
            }
            catch
            {
            }

            // Check if image and then get sizes, make thumb and update database
            var extArray = ("jpeg,jpg,gif,bmp,png,tiff,tif").Split(',');
            var extensions = new List<string>(extArray);
            if (extensions.Contains(ext))
            {
                var fs = new FileStream(Util.MapPath(mediaItemFileUrl), FileMode.Open, FileAccess.Read, FileShare.Read);

                var image = Image.FromStream(fs);
                var fileWidth = image.Width;
                var fileHeight = image.Height;
                fs.Close();
                try
                {
                    mediaItem.getProperty("umbracoWidth").Value = fileWidth.ToString();
                    mediaItem.getProperty("umbracoHeight").Value = fileHeight.ToString();
                }
                catch
                {
                }

                // Generate thumbnails
                var fileNameThumb = Util.MapPath(mediaItemFileUrl.Replace("." + ext, "_thumb.jpg"));
                GenerateThumbnail(image, 100, fileWidth, fileHeight, ext, fileNameThumb);

                image.Dispose();
            }

            try
            {
                mediaItem.getProperty("umbracoFile").Value = mediaItemFileUrl;
            }
            catch
            {
                mediaItem.delete();
                return null;
            }
            mediaItem.XmlGenerate(new XmlDocument());

            return mediaItem;
        }

        /// <summary>
        ///   Generates the thumbnail.
        /// </summary>
        /// <param name = "image">The image.</param>
        /// <param name = "maxWidthHeight">Height of the max width.</param>
        /// <param name = "fileWidth">Width of the file.</param>
        /// <param name = "fileHeight">Height of the file.</param>
        /// <param name = "ext">The ext.</param>
        /// <param name = "thumbnailFileName">Name of the thumbnail file.</param>
        internal static void GenerateThumbnail(
            Image image, int maxWidthHeight, int fileWidth, int fileHeight, string ext, string thumbnailFileName)
        {
            // Generate thumbnail
            var fx = fileWidth / (float)maxWidthHeight;
            var fy = fileHeight / (float)maxWidthHeight;
            // must fit in thumbnail size
            var f = Math.Max(fx, fy); //if (f < 1) f = 1;
            var widthTh = (int)Math.Round(fileWidth / f);
            var heightTh = (int)Math.Round(fileHeight / f);

            // fixes for empty width or height
            if (widthTh == 0)
            {
                widthTh = 1;
            }
            if (heightTh == 0)
            {
                heightTh = 1;
            }

            // Create new image with best quality settings
            var bp = new Bitmap(widthTh, heightTh);
            var g = Graphics.FromImage(bp);
            g.SmoothingMode = SmoothingMode.HighQuality;
            g.InterpolationMode = InterpolationMode.HighQualityBicubic;
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;

            // Copy the old image to the new and resized
            var rect = new Rectangle(0, 0, widthTh, heightTh);
            g.DrawImage(image, rect, 0, 0, image.Width, image.Height, GraphicsUnit.Pixel);

            // Copy metadata
            var codecs = ImageCodecInfo.GetImageEncoders();
            ImageCodecInfo codec = null;

            foreach (var t in codecs.Where(t => t.MimeType.Equals("image/jpeg")))
            {
                codec = t;
            }

            // Set compression ratio to 90%
            var ep = new EncoderParameters();
            ep.Param[0] = new EncoderParameter(Encoder.Quality, 90L);

            // Save the new image
            bp.Save(thumbnailFileName, codec, ep);
            bp.Dispose();
            g.Dispose();
        }
    }
}